Adding new cards with Groovy
by ubeefx
Moderators: ubeefx, beholder, melvin, ShawnieBoy, Lodici, CCGHQ Admins
Re: Adding new cards with Groovy
by melvin » 19 Oct 2013, 13:41
submitted by ember hauler on firemind.ch

Magarena/scripts/Cho_Manno__Revolutionary.txt

Magarena/scripts/Cho_Manno__Revolutionary.txt
- Code: Select all
name=Cho-Manno, Revolutionary
url=http://magiccards.info/10e/en/12.html
image=http://magiccards.info/scans/en/10e/12.jpg
value=2.500
rarity=R
type=Legendary,Creature
subtype=Human,Rebel
cost={2}{W}{W}
pt=2/2
timing=main
requires_groovy_code
- Code: Select all
[
new MagicIfDamageWouldBeDealtTrigger(MagicTrigger.PREVENT_DAMAGE) {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicDamage damage) {
if (damage.getTarget() == permanent) {
// Replacement effect. Generates no event or action.
damage.prevent();
}
return MagicEvent.NONE;
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by melvin » 19 Oct 2013, 13:42
submitted by Jericho Pumpkin on firemind.ch

Magarena/scripts/Rusted_Relic.txt

Magarena/scripts/Rusted_Relic.txt
- Code: Select all
name=Rusted Relic
url=http://magiccards.info/som/en/199.html
image=http://magiccards.info/scans/en/som/199.jpg
value=3.269
rarity=U
type=Artifact
cost={4}
timing=artifact
requires_groovy_code
- Code: Select all
[
new MagicStatic(MagicLayer.SetPT) {
@Override
public void modPowerToughness(final MagicPermanent source,final MagicPermanent permanent,final MagicPowerToughness pt) {
pt.set(5,5);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicCondition.METALCRAFT_CONDITION.accept(source);
}
},
new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
flags.add(MagicSubType.Golem);
}
@Override
public int getTypeFlags(final MagicPermanent permanent,final int flags) {
return flags |
MagicType.Artifact.getMask() |
MagicType.Creature.getMask();
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicCondition.METALCRAFT_CONDITION.accept(source);
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by jerichopumpkin » 20 Oct 2013, 12:42
I've submitted Wings of Velis Vel and Shields of Velis Vel before noticing that there was an error, here is the correct version of the groovy code:
Wings_of_Velis_Vel.groovy
Elvish_Vanguard.groovy
Sorry for the mistakes, I really need to do the testing with a clearer state of mind
Wings_of_Velis_Vel.groovy
- Code: Select all
def PT = new MagicStatic(MagicLayer.SetPT, MagicStatic.UntilEOT) {
@Override
public void modPowerToughness(final MagicPermanent source,final MagicPermanent permanent,final MagicPowerToughness pt) {
pt.set(4,4);
}
};
def AB = new MagicStatic(MagicLayer.Ability, MagicStatic.UntilEOT) {
@Override
public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
flags.add(MagicAbility.Flying);
}
};
def TP = new MagicStatic(MagicLayer.Type, MagicStatic.UntilEOT) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
flags.addAll(MagicSubType.ALL_CREATURES);
}
};
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_CREATURE,
new MagicDestroyTargetPicker(true),
this,
"Target creature\$ becomes 4/4, gains all creature types and flying until the end of the turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game, {
MagicPermanent creature ->
game.doAction(new MagicBecomesCreatureAction(creature,PT,AB,TP));
} as MagicPermanentAction);
}
}
]
- Code: Select all
[
new MagicSpellCardEvent() {
@Override
public MagicEvent getEvent(final MagicCardOnStack cardOnStack,final MagicPayedCost payedCost) {
return new MagicEvent(
cardOnStack,
MagicTargetChoice.POS_TARGET_PLAYER,
this,
"Creature PN controls get +0/+1 and gains all creature types until the end of the turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPlayer(game,new MagicPlayerAction() {
public void doAction(final MagicPlayer player) {
final MagicStatic ST = new MagicStatic(MagicLayer.Type, MagicStatic.UntilEOT) {
@Override
public void modSubTypeFlags(
final MagicPermanent P,
final Set<MagicSubType> flags) {
flags.addAll(MagicSubType.ALL_CREATURES);
}
};
final Collection<MagicPermanent> targets = game.filterPermanents(player, MagicTargetFilter.TARGET_CREATURE_YOU_CONTROL);
for (final MagicPermanent creature : targets) {
game.doAction(new MagicChangeTurnPTAction(creature,0,1));
game.doAction(new MagicBecomesCreatureAction(creature,ST));
}
}
});
}
}
]
Elvish_Vanguard.groovy
- Code: Select all
[
new MagicWhenOtherComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPermanent otherPermanent) {
return (otherPermanent != permanent &&
otherPermanent.hasSubType(MagicSubType.Elf)) ?
new MagicEvent(
permanent,
this,
"Put a +1/+1 counter on SN."
):
MagicEvent.NONE;
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.doAction(new MagicChangeCountersAction(event.getPermanent(),MagicCounterType.PlusOne,1,true));
}
}
]
Sorry for the mistakes, I really need to do the testing with a clearer state of mind

- jerichopumpkin
- Posts: 212
- Joined: 12 Sep 2013, 11:21
- Has thanked: 19 times
- Been thanked: 13 times
Re: Adding new cards with Groovy
by melvin » 21 Oct 2013, 05:04
Thanks for the fixes. What's wrong with Elvish Branchbender? If it is about the X/X being a fixed number problem, I've fixed it.

Magarena/scripts/Elvish_Branchbender.txt

Magarena/scripts/Elvish_Branchbender.txt
- Code: Select all
name=Elvish Branchbender
url=http://magiccards.info/lw/en/204.html
image=http://magiccards.info/scans/en/lw/204.jpg
value=3.500
rarity=C
type=Creature
subtype=Elf,Druid
cost={2}{G}
pt=2/2
timing=main
requires_groovy_code
- Code: Select all
def ST = new MagicStatic(MagicLayer.Type, MagicStatic.UntilEOT) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
flags.add(MagicSubType.Treefolk);
}
@Override
public int getTypeFlags(final MagicPermanent permanent,final int flags) {
return flags|MagicType.Creature.getMask();
}
};
[
new MagicPermanentActivation(
new MagicActivationHints(MagicTiming.Animate),
"Animate"
) {
@Override
public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
return [new MagicTapEvent(source)];
}
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
MagicTargetChoice.Positive("target Forest"),
this,
"Until end of turn, target Forest\$ becomes an X/X Treefolk creature in addition to its other types, " +
"where X is the number of Elves you control."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
event.processTargetPermanent(game, {
final MagicPermanent land ->
final int amount = event.getPlayer().getNrOfPermanents(MagicSubType.Elf);
final MagicStatic PT = new MagicStatic(MagicLayer.SetPT, MagicStatic.UntilEOT) {
@Override
public void modPowerToughness(final MagicPermanent source,final MagicPermanent permanent,final MagicPowerToughness pt) {
pt.set(amount,amount);
}
};
game.doAction(new MagicBecomesCreatureAction(land,PT,ST));
} as MagicPermanentAction);
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by jerichopumpkin » 21 Oct 2013, 09:20
Thanks for the fix, I was not able to find out how to do it, so targetting a Forest controlled by the opponent produced a 0/0 Treefolk (too good to be true, but wrongmelvin wrote:Thanks for the fixes. What's wrong with Elvish Branchbender? If it is about the X/X being a fixed number problem, I've fixed it.

Yet another little piece of know-how for me!
- jerichopumpkin
- Posts: 212
- Joined: 12 Sep 2013, 11:21
- Has thanked: 19 times
- Been thanked: 13 times
Re: Adding new cards with Groovy
by melvin » 22 Oct 2013, 05:40

Magarena/scripts/Elspeth__Sun_s_Champion.txt
- Code: Select all
name=Elspeth, Sun's Champion
url=http://magiccards.info/ths/en/9.html
image=http://magiccards.info/scans/en/ths/9.jpg
value=4.039
rarity=M
type=Planeswalker
subtype=Elspeth
cost={4}{W}{W}
ability=enters with charge 4
timing=main
requires_groovy_code
- Code: Select all
[
new MagicPlaneswalkerActivation(1) {
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
this,
"Put three 1/1 white Soldier creature tokens onto the battlefield."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.doAction(new MagicPlayTokensAction(
event.getPlayer(),
TokenCardDefinitions.get("1/1 white Soldier creature token"),
3
));
}
},
new MagicPlaneswalkerActivation(-3) {
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
this,
"Destroy all creatures with power 4 or greater."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.doAction(new MagicDestroyAction(
game.filterPermanents(MagicTargetFilter.TARGET_CREATURE_POWER_4_OR_MORE)
));
}
},
new MagicPlaneswalkerActivation(-7) {
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
this,
"PN gets an emblem with \"Creatures you control get +2/+2 and have flying.\""
);
}
@Override
public void executeEvent(final MagicGame outerGame, final MagicEvent event) {
outerGame.doAction(new MagicAddStaticAction(
new MagicStatic(
MagicLayer.ModPT,
MagicTargetFilter.ANY
) {
@Override
public void modPowerToughness(final MagicPermanent source,final MagicPermanent permanent,final MagicPowerToughness pt) {
pt.add(2, 2);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return target.getController().getId() == event.getPlayer().getId() && target.isCreature();
}
}
));
outerGame.doAction(new MagicAddStaticAction(
new MagicStatic(
MagicLayer.Ability,
MagicTargetFilter.ANY
) {
@Override
public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
flags.add(MagicAbility.Flying);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return target.getController().getId() == event.getPlayer().getId() && target.isCreature();
}
}
));
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by jerichopumpkin » 23 Oct 2013, 10:07

Duplicant.txt
- Code: Select all
name=Duplicant
url=http://magiccards.info/cma/en/7.html
image=http://magiccards.info/scans/en/cma/7.jpg
value=4.413
rarity=R
type=Artifact,Creature
subtype=Shapeshifter
cost={6}
pt=2/4
timing=artifact
requires_groovy_code
- Code: Select all
def NONTOKEN_CREATURE = new MagicPermanentFilterImpl() {
public boolean accept(final MagicGame game,final MagicPlayer player,final MagicPermanent target) {
return target.isCreature() && !target.isToken();
}
};
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
final MagicTargetChoice targetChoice = new MagicTargetChoice(
new MagicOtherPermanentTargetFilter(
NONTOKEN_CREATURE,
permanent
),
MagicTargetHint.None,
"another target nontoken creature to exile"
);
return new MagicEvent(
permanent,
new MagicMayChoice(targetChoice),
MagicExileTargetPicker.create(),
this,
"PN may\$ exile another target nontoken creature\$."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
final MagicPermanent source = event.getPermanent();
final MagicCardList exiled = source.getExiledCards();
if (event.isYes()) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent target) {
game.doAction(new MagicRemoveFromPlayAction(target, MagicLocationType.Exile));
exiled.addToTop(target.getCard());
}
});
}else{
exiled.addToTop(MagicCard.NONE);
}
}
},
new MagicStatic(MagicLayer.SetPT) {
@Override
public void modPowerToughness(final MagicPermanent source,final MagicPermanent permanent,final MagicPowerToughness pt) {
final MagicCardList exiled = permanent.getExiledCards();
final MagicCard card = exiled.getCardAtTop();
if (card != MagicCard.NONE) {
pt.set(card.getPower(),card.getToughness());
}
}
},
new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
final MagicCardList exiled = permanent.getExiledCards();
final MagicCard card = exiled.getCardAtTop();
if (card != MagicCard.NONE) {
final EnumSet<MagicSubType> subtypes = MagicSubType.getSubTypes(card.getCardDefinition().getSubTypeString());
flags.addAll(subtypes);
}
}
}
]
- jerichopumpkin
- Posts: 212
- Joined: 12 Sep 2013, 11:21
- Has thanked: 19 times
- Been thanked: 13 times
Re: Adding new cards with Groovy
by melvin » 29 Oct 2013, 06:06
Submitted by hong yie on firemind.ch

Magarena/scripts/Silverglade_Elemental.txt

Magarena/scripts/Silverglade_Elemental.txt
- Code: Select all
name=Silverglade Elemental
url=http://magiccards.info/pch/en/78.html
image=http://magiccards.info/scans/en/pch/78.jpg
value=4.095
rarity=C
type=Creature
subtype=Elemental
cost={4}{G}
pt=4/4
timing=main
requires_groovy_code
- Code: Select all
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPayedCost payedCost) {
return new MagicEvent(
permanent,
new MagicMayChoice(),
this,
"PN may\$ search his or her library for a Forest card and put that card onto the battlefield, then shuffle PN's library."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
game.addEvent(new MagicSearchOntoBattlefieldEvent(
event,
new MagicTargetChoice("a Forest card from your library")
));
}
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by melvin » 29 Oct 2013, 06:07
Submitted by hong yie on firemind.ch

Magarena/scripts/Argothian_Wurm.txt

Magarena/scripts/Argothian_Wurm.txt
- Code: Select all
name=Argothian Wurm
url=http://magiccards.info/us/en/236.html
image=http://magiccards.info/scans/en/us/236.jpg
value=3.890
rarity=R
type=Creature
subtype=Wurm
cost={3}{G}
pt=6/6
ability=trample
timing=main
requires_groovy_code
- Code: Select all
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
return new MagicEvent(
permanent,
permanent.getOpponent(),
new MagicMayChoice(MagicTargetChoice.SACRIFICE_LAND),
this,
"PN may\$ sacrifice a land\$. If a he or she does, put SN on the top of its owner's library."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
event.processTargetPermanent(game,new MagicPermanentAction() {
public void doAction(final MagicPermanent creature) {
game.doAction(new MagicSacrificeAction(creature));
game.doAction(new MagicRemoveFromPlayAction(
event.getPermanent(),
MagicLocationType.TopOfOwnersLibrary
));
}
});
}
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by melvin » 31 Oct 2013, 09:20
submitted by Jericho Pumpkin on http://firemind.ch

Magarena/scripts/Spellbinder.txt

Magarena/scripts/Spellbinder.txt
- Code: Select all
name=Spellbinder
url=http://magiccards.info/ds/en/143.html
image=http://magiccards.info/scans/en/ds/143.jpg
value=3.207
rarity=R
type=Artifact
subtype=Equipment
cost={3}
equip={4}
timing=artifact
requires_groovy_code
- Code: Select all
def INSTANT_FROM_HAND = new MagicCardFilterImpl() {
public boolean accept(final MagicGame game,final MagicPlayer player,final MagicCard target) {
return target.hasType(MagicType.Instant);
}
public boolean acceptType(final MagicTargetType targetType) {
return targetType == MagicTargetType.Hand;
}
};
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
final MagicTargetChoice targetChoice = new MagicTargetChoice(
INSTANT_FROM_HAND,
MagicTargetHint.None,
"an instant card from your hand"
);
return new MagicEvent(
permanent,
new MagicMayChoice(targetChoice),
MagicGraveyardTargetPicker.PutOntoBattlefield,
this,
"PN may\$ exile an instant card\$ from his or her hand."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
event.processTargetCard(game,new MagicCardAction() {
public void doAction(final MagicCard target) {
game.doAction(new MagicExileUntilThisLeavesPlayAction(
event.getPermanent(),
target,
MagicLocationType.OwnersHand
));
}
});
}
}
},
new MagicWhenDamageIsDealtTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game, final MagicPermanent permanent, final MagicDamage damage) {
return (permanent.getEquippedCreature() == damage.getSource() &&
damage.getTarget().isPlayer() &&
damage.isCombat()) ?
new MagicEvent(
permanent,
new MagicMayChoice(),
permanent.getExiledCard(),
this,
"PN may\$ cast a copy of RN without paying its mana cost."
) :
MagicEvent.NONE;
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
if (event.isYes()) {
game.doAction(new MagicCastFreeCopyAction(
event.getPlayer(),
event.getRefCard()
));
}
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by melvin » 02 Nov 2013, 05:27
Support for "scry 1" just landed in 1.44 development as MagicScryEvent in groovy code.

Magarena/scripts/Temple_of_Silence.txt

Magarena/scripts/Temple_of_Silence.txt
- Code: Select all
name=Temple of Silence
url=http://magiccards.info/ths/en/227.html
image=http://magiccards.info/scans/en/ths/227.jpg
value=3.792
rarity=R
type=Land
mana=w3b3
ability=tap add mana {W} or {B};\
enters tapped
timing=tapland
requires_groovy_code
- Code: Select all
[
new MagicWhenComesIntoPlayTrigger() {
@Override
public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent, final MagicPayedCost payedCost) {
return new MagicEvent(
permanent,
this,
"Look at the top card of your library. You may put that card on the bottom of your library."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.addEvent(new MagicScryEvent(event));
}
}
]
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by Huggybaby » 03 Nov 2013, 01:51
Holy cow, this progress lately is getting hard to believe.
-
Huggybaby - Administrator
- Posts: 3226
- Joined: 15 Jan 2006, 19:44
- Location: Finally out of Atlanta
- Has thanked: 742 times
- Been thanked: 601 times
Re: Adding new cards with Groovy
by ember hauler » 04 Nov 2013, 18:17
True.Huggybaby wrote:Holy cow, this progress lately is getting hard to believe.
Every new montly release is so cool to get.
Personnaly I'm very impressed with the new work on ability= in card scripting. Powerful stuff!
I've compiled a kind of cheat sheet for these effects and keywords and was astonished by the length of the list of things that are already implemented.
- ember hauler
- Posts: 79
- Joined: 14 Aug 2013, 08:13
- Has thanked: 27 times
- Been thanked: 14 times
Re: Adding new cards with Groovy
by melvin » 05 Nov 2013, 01:49
Sounds like it would be useful on our wiki page. Would you be able to share this cheat sheet with us?ember hauler wrote:I've compiled a kind of cheat sheet for these effects and keywords and was astonished by the length of the list of things that are already implemented.
-
melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 459 times
Re: Adding new cards with Groovy
by Huggybaby » 05 Nov 2013, 05:32
I was going to ask for the cheat sheet too, but I didn't want to sound, you know, ignorant. 
And it would be useful to see what remains to be done!
And then I'd like to hear melvin comment on these abilities, and the AI's ability to use them. Ubeefx left everything out that the AI couldn't use well, and that's something that should be kept in mind as a guiding principle for Magarena.

And it would be useful to see what remains to be done!
And then I'd like to hear melvin comment on these abilities, and the AI's ability to use them. Ubeefx left everything out that the AI couldn't use well, and that's something that should be kept in mind as a guiding principle for Magarena.
-
Huggybaby - Administrator
- Posts: 3226
- Joined: 15 Jan 2006, 19:44
- Location: Finally out of Atlanta
- Has thanked: 742 times
- Been thanked: 601 times
Who is online
Users browsing this forum: No registered users and 4 guests