Contrib. Coll.
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
40 posts
• Page 1 of 3 • 1, 2, 3
Contrib. Coll.
by Hellfish » 11 Jun 2010, 13:27
Or, Contribution Collection 
I'll be posting a bunch of cards here, as soon as I've tested them tonight/some of them tomorrow. I thought this was neater,more organized than dumping them all in the middle of another thread.
Coming soon:
Adarkar Wastes
Brushland
Karplusan Forest
Sulfurous Springs
Underground River
Battlefield Forge
Caves of Koilos
Llanowar Wastes
Shivan Reef
Yavimaya Coast
Salt Flats
Pine Barrens
Skyshroud Forest
Caldera Lake
Scabland
Talisman of Dominance
Talisman of Impulse
Talisman of Indulgence
Talisman of Progress
Talisman of Unity
NOTE: The above pain-manasources will be keyworded. There was very old, non-functional code for them in Ability_Mana that I aim to replace.
Muddle the Mixture
Journey to Nowhere
Trusted Advisor
NOTE: Trusted Advisor also needs my HandSize keyword.

I'll be posting a bunch of cards here, as soon as I've tested them tonight/some of them tomorrow. I thought this was neater,more organized than dumping them all in the middle of another thread.
Coming soon:
Adarkar Wastes
Brushland
Karplusan Forest
Sulfurous Springs
Underground River
Battlefield Forge
Caves of Koilos
Llanowar Wastes
Shivan Reef
Yavimaya Coast
Salt Flats
Pine Barrens
Skyshroud Forest
Caldera Lake
Scabland
Talisman of Dominance
Talisman of Impulse
Talisman of Indulgence
Talisman of Progress
Talisman of Unity
NOTE: The above pain-manasources will be keyworded. There was very old, non-functional code for them in Ability_Mana that I aim to replace.
Muddle the Mixture
Journey to Nowhere
Trusted Advisor
NOTE: Trusted Advisor also needs my HandSize keyword.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Contrib. Coll.
by Beached As » 11 Jun 2010, 16:18
Nice work man! With this we'll be getting close to 3500 cards
.

- Beached As
- Programmer
- Posts: 110
- Joined: 23 Feb 2010, 07:48
- Has thanked: 0 time
- Been thanked: 0 time
Re: Contrib. Coll.
by Hellfish » 11 Jun 2010, 17:38
Thanks! 3500's gonna be sweet. Just 12000 to go
But now...
Here comes the pain(lands)!
Add this either just in CardFactory before the links to the specific factories OR at the end of CardFactory and at the end of CardFactory_Lands.
Yes, I know, all pain lands do only 1 damage but flexibility isn't a bad thing, for neither custom or possibly upcoming cards.
cards.txt entries:
The one thing about this is that the pain mana can be used directly in payment, like ordinary lands. This means that if the painland can only produce one type of mana needed for the cost (for instance, tapping an Adarkar Wastes during payment for an Akrasan Squire) it will not ask for confirmation and just use the mana and deal the damage directly. It *can* be rewritten into a normal ability, though, so it's not a huge issue but then you won't be able to use that mana like ordinary lands.

Here comes the pain(lands)!
Add this either just in CardFactory before the links to the specific factories OR at the end of CardFactory and at the end of CardFactory_Lands.
- Code: Select all
while(hasKeyword(card,"paintap") != -1)
{
String toParse = card.getIntrinsicKeyword().get(hasKeyword(card,"paintap"));
card.removeIntrinsicKeyword(toParse);
String[] splitkeyword = toParse.split(":");
final int amountHurt = Integer.parseInt(splitkeyword[1]);
final String manaGenerated = splitkeyword[2];
final Ability_Mana addMana = new Ability_Mana(card, "tap: add " + manaGenerated + " to your mana pool.CARDNAME deals " + amountHurt + " damage to you.") {
private static final long serialVersionUID = -259088242789L;
@Override
public void resolve()
{
AllZone.GameAction.getPlayerLife(getController()).subtractLife(amountHurt);
super.resolve();
}
@Override
public String mana() {
return manaGenerated;
}
};
card.addSpellAbility(addMana);
}//paintap
Yes, I know, all pain lands do only 1 damage but flexibility isn't a bad thing, for neither custom or possibly upcoming cards.
cards.txt entries:
- Code: Select all
Adarkar Wastes
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:U
Brushland
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:G
Karplusan Forest
no cost
Land
no text
tap: add 1
paintap:1:R
paintap:1:G
Sulfurous Springs
no cost
Land
no text
tap: add 1
paintap:1:B
paintap:1:R
Underground River
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:B
Battlefield Forge
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:R
Caves of Koilos
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:B
Llanowar Wastes
no cost
Land
no text
tap: add 1
paintap:1:B
paintap:1:G
Shivan Reef
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:R
Yavimaya Coast
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:G
Salt Flats
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:B
Comes into play tapped.
Pine Barrens
no cost
Land
no text
tap: add 1
paintap:1:B
paintap:1:G
Comes into play tapped.
Skyshroud Forest
no cost
Land
no text
tap: add 1
paintap:1:G
paintap:1:U
Comes into play tapped.
Caldera Lake
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:R
Comes into play tapped.
Scabland
no cost
Land
no text
tap: add 1
paintap:1:R
paintap:1:W
Comes into play tapped.
Talisman of Dominance
2
Artifact
no text
tap: add 1
paintap:1:U
paintap:1:B
Talisman of Impulse
2
Artifact
no text
tap: add 1
paintap:1:R
paintap:1:G
Talisman of Indulgence
2
Artifact
no text
tap: add 1
paintap:1:B
paintap:1:R
Talisman of Progress
2
Artifact
no text
tap: add 1
paintap:1:W
paintap:1:U
Talisman of Unity
2
Artifact
no text
tap: add 1
paintap:1:G
paintap:1:W
- Code: Select all
//pain lands
ArrayList<String> pain = new ArrayList<String>();
pain.add("Battlefield Forge");
pain.add("Caves of Koilos");
pain.add("Llanowar Wastes");
pain.add("Shivan Reef");
pain.add("Yavimaya Coast");
pain.add("Adarkar Wastes");
pain.add("Brushland");
pain.add("Karplusan Forest");
pain.add("Underground River");
pain.add("Sulfurous Springs");
if(pain.contains(sourceCard.getName()) && !Mana.equals("1")) runcommands.add(new Command() {
private static final long serialVersionUID = -5904507275105961979L;
public void execute() {
AllZone.GameAction.getPlayerLife(getController()).subtractLife(1);
}
});
The one thing about this is that the pain mana can be used directly in payment, like ordinary lands. This means that if the painland can only produce one type of mana needed for the cost (for instance, tapping an Adarkar Wastes during payment for an Akrasan Squire) it will not ask for confirmation and just use the mana and deal the damage directly. It *can* be rewritten into a normal ability, though, so it's not a huge issue but then you won't be able to use that mana like ordinary lands.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Contrib. Coll.
by Hellfish » 11 Jun 2010, 18:06
Here goes Journey to Nowhere
cards.txt:
- Code: Select all
//*************** START *********** START **************************
else if(cardName.equals("Journey to Nowhere")) {
final CommandReturn getPerm = new CommandReturn() {
public Object execute() {
//get all creatures
CardList tempList = new CardList();
tempList.addAll(AllZone.Human_Play.getCards());
tempList.addAll(AllZone.Computer_Play.getCards());
CardList list = new CardList();
for(int i = 0; i < tempList.size(); i++) {
if(tempList.get(i).isPermanent() && tempList.get(i).isCreature()
&& CardFactoryUtil.canTarget(card, tempList.get(i))) list.add(tempList.get(i));
}
//remove "this card"
list.remove(card);
return list;
}
};//CommandReturn
final SpellAbility abilityComes = new Ability(card, "0") {
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
AllZone.GameAction.removeFromGame(getTargetCard());
}
}//resolve()
};
final Input inputComes = new Input() {
private static final long serialVersionUID = -3613946694360326887L;
@Override
public void showMessage() {
CardList choice = (CardList) getPerm.execute();
stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice,
"Select target creature to remove from the game", true, false));
ButtonUtil.disableAll();//to disable the Cancel button
}
};
Command commandComes = new Command() {
private static final long serialVersionUID = -6250376920501373535L;
public void execute() {
CardList perm = (CardList) getPerm.execute();
String s = card.getController();
if(perm.size() == 0) return;
else if(s.equals(Constant.Player.Human)) AllZone.InputControl.setInput(inputComes);
else //computer
{
Card target;
//try to target human creature
CardList human = CardFactoryUtil.AI_getHumanCreature(card, true);
target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty
// try to target human permanent
if(target == null) {
int convertedCost = 0;
CardList tempList = new CardList();
tempList.addAll(AllZone.Human_Play.getCards());
for(int i = 0; i < tempList.size(); i++) {
if(tempList.get(i).isPermanent()
&& !tempList.get(i).isLand()
&& CardFactoryUtil.canTarget(card, tempList.get(i))
&& (CardUtil.getConvertedManaCost(tempList.get(i).getManaCost()) > convertedCost)) {
target = tempList.get(i);
convertedCost = CardUtil.getConvertedManaCost(tempList.get(i).getManaCost());
}
}
}
//target something cheaper (manacost 0?) instead:
if(target == null) {
CardList humanPerms = new CardList();
humanPerms.addAll(AllZone.Human_Play.getCards());
humanPerms = humanPerms.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isPermanent() && !c.isLand() && CardFactoryUtil.canTarget(card, c);
}
});
if(humanPerms.size() > 0) target = humanPerms.get(0);
}
if(target == null) {
//must target computer creature
CardList computer = new CardList(AllZone.Computer_Play.getCards());
computer = computer.getType("Creature");
computer.remove(card);
computer.shuffle();
if(computer.size() != 0) target = computer.get(0);
else target = card;
}
abilityComes.setTargetCard(target);
AllZone.Stack.add(abilityComes);
}//else
}//execute()
};//CommandComes
Command commandLeavesPlay = new Command() {
private static final long serialVersionUID = 6997038208952910355L;
public void execute() {
Object o = abilityComes.getTargetCard();
if(o == null || ((Card) o).isToken() || !AllZone.GameAction.isCardRemovedFromGame((Card) o)) return;
SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
//copy card to reset card attributes like attack and defense
Card c = abilityComes.getTargetCard();
if(!c.isToken()) {
c = AllZone.CardFactory.dynamicCopyCard(c);
c.setController(c.getOwner());
PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner());
PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner());
removed.remove(c);
if (c.isTapped())
c.untap();
play.add(c);
}
}//resolve()
};//SpellAbility
ability.setStackDescription("Journey to Nowhere - returning creature to play.");
AllZone.Stack.add(ability);
}//execute()
};//Command
card.addComesIntoPlayCommand(commandComes);
card.addLeavesPlayCommand(commandLeavesPlay);
card.setSVar("PlayMain1", "TRUE");
card.clearSpellAbility();
card.addSpellAbility(new Spell_Permanent(card) {
private static final long serialVersionUID = -3250095291930182087L;
@Override
public boolean canPlayAI() {
Object o = getPerm.execute();
if(o == null) return false;
CardList cList = new CardList(AllZone.Human_Play.getCards());
cList = cList.filter(new CardListFilter()
{
public boolean addCard(Card crd)
{
return CardFactoryUtil.canTarget(card, crd) && crd.isCreature();
}
});
CardList cl = (CardList) getPerm.execute();
return (o != null) && cList.size() > 0 && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand);
}
});
}//*************** END ************ END **************************
cards.txt:
- Code: Select all
Journey to Nowhere
1 W
Enchantment
When Journey to Nowhere enters the battlefield, exile target creature. When Journey to Nowhere leaves the battlefield, return the exiled card to the battlefield under its owner's control.
Last edited by Hellfish on 12 Jun 2010, 08:24, edited 1 time in total.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Contrib. Coll.
by Hellfish » 11 Jun 2010, 18:11
Muddle the Mixture
Add to CardFactory
cards.txt:
Add to CardFactory
- Code: Select all
//*************** START *********** START **************************
else if(cardName.equals("Muddle the Mixture")) {
SpellAbility spell = new Spell(card) {
private static final long serialVersionUID = -2489268054171391552L;
@Override
public void resolve() {
SpellAbility sa = AllZone.Stack.pop();
AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
}
@Override
public boolean canPlay() {
if(AllZone.Stack.size() == 0) return false;
//see if spell is on stack and that opponent played it
String opponent = AllZone.GameAction.getOpponent(card.getController());
SpellAbility sa = AllZone.Stack.peek();
return sa.isSpell()
&& opponent.equals(sa.getSourceCard().getController())
&& CardFactoryUtil.isCounterable(sa.getSourceCard())
&& (sa.getSourceCard().isInstant() || sa.getSourceCard().isSorcery());
}
};
card.clearSpellAbility();
spell.setDescription("Counter target instant or sorcery spell.");
spell.setStackDescription("Muddle The Mixture - Counters target instant or sorcery.");
card.addSpellAbility(spell);
}//*************** END ************ END **************************
cards.txt:
- Code: Select all
Muddle the Mixture
U U
Instant
no text
Transmute:1 U U
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Contrib. Coll.
by Sloth » 12 Jun 2010, 07:51
You forgot these beauties:
- Code: Select all
Grand Coliseum
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:U
paintap:1:B
paintap:1:R
paintap:1:G
Comes into play tapped.
Elves of Deep Shadow
G
Creature Elf Druid
no text
1/1
paintap:1:B
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Contrib. Coll.
by Hellfish » 12 Jun 2010, 08:30
Oh yeah, thanks for the reminder.Sloth wrote:You forgot these beauties:

So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Contrib. Coll.
by Beached As » 13 Jun 2010, 08:05
I just committed your pain lands and artifacts Hellfish. Yours too Sloth. Thanks very much for the effort 

- Beached As
- Programmer
- Posts: 110
- Joined: 23 Feb 2010, 07:48
- Has thanked: 0 time
- Been thanked: 0 time
Re: Contrib. Coll.
by Chris H. » 14 Jun 2010, 22:20
`
I added Journey To Nowhere to the SVN. I had a few problems but was able to resolve them. Code tested and it works.
And, opps. I will try to remember to lowercase the "to".

-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: Contrib. Coll.
by Chris H. » 15 Jun 2010, 13:31
`Hellfish wrote:Muddle the Mixture
Added Muddle the Mixture. The computer can not use this spell.
You may want to look at the ComputerAI_counterSpells.java and ComputerAI_counterSpells2.java. This code allows the computer to cast counter spells. Unfortunately, code will need to be added to allow this new card to be usable by the AI.

-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: Contrib. Coll.
by Hellfish » 15 Jun 2010, 14:49
Well, I looked into ComputerAI_counterSpell2.java (BTW, is there a good reason for keeping ComputerAI_counterspell.java around? It's not referenced anywhere.) and it turns out it was surprisingly easy to let the AI us MtM
! paste this code in at the beginning of the addCard method used by the CardListFilter in getPlayableCounterspells(final spellAbility sa):

- Code: Select all
if(sa.getSourceCard().getType().contains("Sorcery") || sa.getSourceCard().getType().contains("Instant")) {
if(c.getName().equals("Muddle the Mixture"))
return true;
}
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Contrib. Coll.
by Chris H. » 15 Jun 2010, 15:06
`I will try to add your additions, I think that I will find the place for this code. Thank for the submission.
Merged into the SVN. Works OK.

Last edited by Chris H. on 15 Jun 2010, 15:53, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: Contrib. Coll.
by mtgrares » 15 Jun 2010, 15:50
Nope, you can delete it. ComputerAI_Rats.java used to be around to and that can be deleted also.Hellfish wrote:BTW, is there a good reason for keeping ComputerAI_counterspell.java around? (It's not referenced anywhere.)
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Punch Card
by mtgrares » 15 Jun 2010, 15:56
Punch cards, that does seem like a long time ago. Batch processing at its best (or worse). In high school I wrote about Charles Babbage and punch cards but I've never used one. The Hackers book (early computing, from the late 1950s to the mid-1980s) by Steven Levy talks about punch cards and I read it in high school.Chris H wrote: I took a few intro college courses in the old days. The college did not have personal computers or terminals for it's students. We had to use card punch machines.
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: Contrib. Coll.
by Hellfish » 16 Jun 2010, 11:56
Lost my big reply to stupid IE... >:(
The gist of it was: "Thanks for the tip, rares! I am working on keyword for counterspell-likes, might not pan out but if so I'll have specific code for the following new cards:
Annul
Artifact Blast
Confound
Dismal Failure
Dispel
Dream Fracture
Envelop
Fervent Denial (sans Flashback,I think)
Flash Counter
Hisoka's Defiance
Illumination
Intervene
Mystic Denial
Negate
Rebuff the Wicked
Thoughtbind
"
The gist of it was: "Thanks for the tip, rares! I am working on keyword for counterspell-likes, might not pan out but if so I'll have specific code for the following new cards:
Annul
Artifact Blast
Confound
Dismal Failure
Dispel
Dream Fracture
Envelop
Fervent Denial (sans Flashback,I think)
Flash Counter
Hisoka's Defiance
Illumination
Intervene
Mystic Denial
Negate
Rebuff the Wicked
Thoughtbind
"
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
40 posts
• Page 1 of 3 • 1, 2, 3
Who is online
Users browsing this forum: No registered users and 43 guests