diff --git a/Mage.Sets/src/mage/cards/b/BarracksOfTheThousand.java b/Mage.Sets/src/mage/cards/b/BarracksOfTheThousand.java
new file mode 100644
index 00000000000..5a462272b46
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BarracksOfTheThousand.java
@@ -0,0 +1,56 @@
+package mage.cards.b;
+
+import mage.abilities.common.CastSpellPaidBySourceTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.mana.WhiteManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SuperType;
+import mage.filter.FilterSpell;
+import mage.filter.predicate.Predicates;
+import mage.game.permanent.token.GnomeSoldierStarStarToken;
+
+import java.util.UUID;
+
+/**
+ * @author Susucr
+ */
+public final class BarracksOfTheThousand extends CardImpl {
+
+ private static final FilterSpell filter = new FilterSpell("an artifact or creature spell");
+
+ static {
+ filter.add(Predicates.or(
+ CardType.ARTIFACT.getPredicate(),
+ CardType.CREATURE.getPredicate()
+ ));
+ }
+
+ public BarracksOfTheThousand(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.LAND}, "");
+
+ this.supertype.add(SuperType.LEGENDARY);
+
+ // (Transforms from Thousand Moons Smithy.)
+ this.nightCard = true;
+
+ // {T}: Add {W}.
+ this.addAbility(new WhiteManaAbility());
+
+ // Whenever you cast an artifact or creature spell using mana produced by Barracks of the Thousand, create a white Gnome Soldier artifact creature token with "This creature's power and toughness are each equal to the number of artifacts and/or creatures you control."
+ this.addAbility(new CastSpellPaidBySourceTriggeredAbility(
+ new CreateTokenEffect(new GnomeSoldierStarStarToken()),
+ filter, false
+ ));
+ }
+
+ private BarracksOfTheThousand(final BarracksOfTheThousand card) {
+ super(card);
+ }
+
+ @Override
+ public BarracksOfTheThousand copy() {
+ return new BarracksOfTheThousand(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/t/ThousandMoonsSmithy.java b/Mage.Sets/src/mage/cards/t/ThousandMoonsSmithy.java
new file mode 100644
index 00000000000..112ba0a0071
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThousandMoonsSmithy.java
@@ -0,0 +1,68 @@
+package mage.cards.t;
+
+import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.costs.common.TapTargetCost;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.TransformSourceEffect;
+import mage.abilities.keyword.TransformAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SuperType;
+import mage.constants.TargetController;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TappedPredicate;
+import mage.game.permanent.token.GnomeSoldierStarStarToken;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author Susucr
+ */
+public final class ThousandMoonsSmithy extends CardImpl {
+
+ public static final FilterControlledPermanent filter =
+ new FilterControlledPermanent("untapped artifacts and/or creatures you control");
+
+ static {
+ filter.add(TappedPredicate.UNTAPPED);
+ filter.add(Predicates.or(
+ CardType.CREATURE.getPredicate(),
+ CardType.ARTIFACT.getPredicate()
+ ));
+ }
+
+ public ThousandMoonsSmithy(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{W}{W}");
+ this.secondSideCardClazz = mage.cards.b.BarracksOfTheThousand.class;
+
+ this.supertype.add(SuperType.LEGENDARY);
+
+ // When Thousand Moons Smithy enters the battlefield, create a white Gnome Soldier artifact creature token with "This creature's power and toughness are each equal to the number of artifacts and/or creatures you control."
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GnomeSoldierStarStarToken())));
+
+ // At the beginning of your precombat main phase, you may tap five untapped artifacts and/or creatures you control. If you do, transform Thousand Moons Smithy.
+ this.addAbility(new TransformAbility());
+ this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(
+ new DoIfCostPaid(
+ new TransformSourceEffect(),
+ new TapTargetCost(new TargetControlledPermanent(5, filter))
+ ),
+ TargetController.YOU,
+ false
+ ));
+ }
+
+ private ThousandMoonsSmithy(final ThousandMoonsSmithy card) {
+ super(card);
+ }
+
+ @Override
+ public ThousandMoonsSmithy copy() {
+ return new ThousandMoonsSmithy(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java
index e5d0e73e0ca..bbcf61d6fde 100644
--- a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java
+++ b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java
@@ -54,6 +54,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
cards.add(new SetCardInfo("Another Chance", 90, Rarity.COMMON, mage.cards.a.AnotherChance.class));
cards.add(new SetCardInfo("Armored Kincaller", 174, Rarity.COMMON, mage.cards.a.ArmoredKincaller.class));
cards.add(new SetCardInfo("Attentive Sunscribe", 4, Rarity.COMMON, mage.cards.a.AttentiveSunscribe.class));
+ cards.add(new SetCardInfo("Barracks of the Thousand", 39, Rarity.RARE, mage.cards.b.BarracksOfTheThousand.class));
cards.add(new SetCardInfo("Bartolome del Presidio", 224, Rarity.UNCOMMON, mage.cards.b.BartolomeDelPresidio.class));
cards.add(new SetCardInfo("Basking Capybara", 175, Rarity.COMMON, mage.cards.b.BaskingCapybara.class));
cards.add(new SetCardInfo("Bat Colony", 5, Rarity.UNCOMMON, mage.cards.b.BatColony.class));
@@ -327,6 +328,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
cards.add(new SetCardInfo("The Skullspore Nexus", 212, Rarity.MYTHIC, mage.cards.t.TheSkullsporeNexus.class));
cards.add(new SetCardInfo("Thousand Moons Crackshot", 37, Rarity.COMMON, mage.cards.t.ThousandMoonsCrackshot.class));
cards.add(new SetCardInfo("Thousand Moons Infantry", 38, Rarity.COMMON, mage.cards.t.ThousandMoonsInfantry.class));
+ cards.add(new SetCardInfo("Thousand Moons Smithy", 39, Rarity.RARE, mage.cards.t.ThousandMoonsSmithy.class));
cards.add(new SetCardInfo("Thrashing Brontodon", 216, Rarity.UNCOMMON, mage.cards.t.ThrashingBrontodon.class));
cards.add(new SetCardInfo("Threefold Thunderhulk", 265, Rarity.RARE, mage.cards.t.ThreefoldThunderhulk.class));
cards.add(new SetCardInfo("Throne of the Grim Captain", 266, Rarity.RARE, mage.cards.t.ThroneOfTheGrimCaptain.class));
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/BarracksOfTheThousandTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/BarracksOfTheThousandTest.java
new file mode 100644
index 00000000000..e8f4545b1e4
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/BarracksOfTheThousandTest.java
@@ -0,0 +1,141 @@
+package org.mage.test.cards.single.lci;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author Susucr
+ */
+public class BarracksOfTheThousandTest extends CardTestPlayerBase {
+
+ /**
+ * {@link mage.cards.t.ThousandMoonsSmithy} {2}{W}{W}
+ * Legendary Artifact
+ * When Thousand Moons Smithy enters the battlefield, create a white Gnome Soldier artifact creature token with “This creature’s power and toughness are each equal to the number of artifacts and/or creatures you control.”
+ * At the beginning of your precombat main phase, you may tap five untapped artifacts and/or creatures you control. If you do, transform Thousand Moons Smithy.
+ */
+ private static final String smithy = "Thousand Moons Smithy";
+ /**
+ * {@link mage.cards.b.BarracksOfTheThousand}
+ * Legendary Artifact Land
+ * {T}: Add {W}.
+ * Whenever you cast an artifact or creature spell using mana produced by Barracks of the Thousand, create a white Gnome Soldier artifact creature token with “This creature’s power and toughness are each equal to the number of artifacts and/or creatures you control.”
+ */
+ private static final String barracks = "Barracks of the Thousand";
+
+ private void initToTransform() {
+ addCard(Zone.BATTLEFIELD, playerA, smithy);
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
+ addCard(Zone.BATTLEFIELD, playerA, "Bear Cub");
+ addCard(Zone.BATTLEFIELD, playerA, "Forest Bear");
+ addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears");
+ addCard(Zone.BATTLEFIELD, playerA, "Runeclaw Bear");
+
+ // First mainphase, transform the smithy tapping all the bears
+ setChoice(playerA, true); // yes to "you may tap"
+ setChoice(playerA, "Balduvian Bears^Bear Cub^Forest Bear^Grizzly Bears^Runeclaw Bear");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ }
+
+ @Test
+ public void trigger_simple() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.HAND, playerA, "Arcbound Worker", 1);
+ initToTransform();
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Arcbound Worker");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Gnome Soldier Token", 1);
+ assertPermanentCount(playerA, "Arcbound Worker", 1);
+ }
+
+ @Test
+ public void trigger_onlyonce_doublemana() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.BATTLEFIELD, playerB, "Heartbeat of Spring");
+ addCard(Zone.HAND, playerA, "Armored Warhorse");
+ initToTransform();
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Armored Warhorse");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Gnome Soldier Token", 1);
+ assertPermanentCount(playerA, "Armored Warhorse", 1);
+ }
+
+
+ @Test
+ public void noTrigger_NotPaidWithBarrack() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.HAND, playerA, "Memnite", 1);
+ initToTransform();
+
+ // Memnite cost 0 so no mana is spend from Barracks.
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Memnite");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Gnome Soldier Token", 0);
+ assertPermanentCount(playerA, "Memnite", 1);
+ }
+
+ @Test
+ public void noTrigger_notCheck() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
+ addCard(Zone.HAND, playerA, "Divination", 1);
+ initToTransform();
+
+ // Sorcery, doesn't trigger Barrack
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Divination");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Gnome Soldier Token", 0);
+ assertGraveyardCount(playerA, "Divination", 1);
+ }
+
+ @Test
+ public void noTrigger_afterRemand() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.HAND, playerB, "Remand");
+ addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
+
+ addCard(Zone.HAND, playerA, "Arcbound Worker");
+ addCard(Zone.HAND, playerA, "Plains", 1); // to cast the second time
+ initToTransform();
+
+ castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Arcbound Worker");
+ castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerB, "Remand", "Arcbound Worker", "Arcbound Worker");
+
+ checkGraveyardCount("Remand in graveyard", 3, PhaseStep.BEGIN_COMBAT, playerB, "Remand", 1);
+ checkHandCardCount("Worker in hand", 3, PhaseStep.BEGIN_COMBAT, playerA, "Arcbound Worker", 1);
+ checkPermanentCount("Gnome Soldier Token on battlefield", 3, PhaseStep.BEGIN_COMBAT, playerA, "Gnome Soldier Token", 1);
+
+ playLand(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Plains");
+ waitStackResolved(3, PhaseStep.POSTCOMBAT_MAIN);
+ castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Arcbound Worker");
+
+ setStopAt(3, PhaseStep.END_TURN);
+ execute();
+
+ assertPermanentCount(playerA, "Gnome Soldier Token", 1);
+ assertPermanentCount(playerA, "Arcbound Worker", 1);
+ assertGraveyardCount(playerB, "Remand", 1);
+ }
+
+}
diff --git a/Mage/src/main/java/mage/abilities/common/CastSpellPaidBySourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CastSpellPaidBySourceTriggeredAbility.java
new file mode 100644
index 00000000000..501f68e9c74
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/common/CastSpellPaidBySourceTriggeredAbility.java
@@ -0,0 +1,77 @@
+package mage.abilities.common;
+
+
+import mage.MageObjectReference;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.effects.Effect;
+import mage.constants.Zone;
+import mage.filter.FilterSpell;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.stack.Spell;
+import mage.target.targetpointer.FixedTarget;
+import mage.watchers.common.ManaPaidObjectSourceWatcher;
+
+/**
+ * @author Susucr
+ */
+public class CastSpellPaidBySourceTriggeredAbility extends TriggeredAbilityImpl {
+
+ private final FilterSpell filter;
+ private final boolean setTargetPointer;
+
+ public CastSpellPaidBySourceTriggeredAbility(Effect effect, FilterSpell filter, boolean setTargetPointer) {
+ super(Zone.BATTLEFIELD, effect);
+ setTriggerPhrase("Whenever you cast " + filter.getMessage() + " using mana produced by {this}, ");
+ addWatcher(new ManaPaidObjectSourceWatcher());
+
+ this.filter = filter;
+ this.setTargetPointer = setTargetPointer;
+ }
+
+ protected CastSpellPaidBySourceTriggeredAbility(final CastSpellPaidBySourceTriggeredAbility ability) {
+ super(ability);
+ this.filter = ability.filter;
+ this.setTargetPointer = ability.setTargetPointer;
+ }
+
+ @Override
+ public CastSpellPaidBySourceTriggeredAbility copy() {
+ return new CastSpellPaidBySourceTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.SPELL_CAST;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (!controllerId.equals(event.getPlayerId())) {
+ return false;
+ }
+
+ Spell spell = game.getSpell(event.getTargetId());
+ if (spell == null || !this.filter.match(spell, controllerId, this, game)) {
+ return false;
+ }
+
+ ManaPaidObjectSourceWatcher watcher = game.getState().getWatcher(ManaPaidObjectSourceWatcher.class);
+ if (watcher == null) {
+ return false;
+ }
+
+ if (!watcher.checkManaFromSourceWasUsedToPay(
+ new MageObjectReference(sourceId, game),
+ new MageObjectReference(spell.getSourceId(), game)
+ )) {
+ return false;
+ }
+
+ if (setTargetPointer) {
+ this.getAllEffects().setTargetPointer(new FixedTarget(spell.getId(), game));
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Mage/src/main/java/mage/game/permanent/token/GnomeSoldierStarStarToken.java b/Mage/src/main/java/mage/game/permanent/token/GnomeSoldierStarStarToken.java
new file mode 100644
index 00000000000..26ce636116f
--- /dev/null
+++ b/Mage/src/main/java/mage/game/permanent/token/GnomeSoldierStarStarToken.java
@@ -0,0 +1,49 @@
+package mage.game.permanent.token;
+
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+
+/**
+ * @author Susucr
+ */
+public final class GnomeSoldierStarStarToken extends TokenImpl {
+
+ private static final FilterControlledPermanent filter = new FilterControlledPermanent();
+
+ static {
+ filter.add(Predicates.or(
+ CardType.ARTIFACT.getPredicate(),
+ CardType.CREATURE.getPredicate()
+ ));
+ }
+
+ private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
+
+ public GnomeSoldierStarStarToken() {
+ super("Gnome Soldier Token", "white Gnome Soldier artifact creature token with "
+ + "\"this creature's power and toughness are each equal to the number of artifacts and/or creatures you control.\"");
+ cardType.add(CardType.ARTIFACT);
+ cardType.add(CardType.CREATURE);
+ subtype.add(SubType.GNOME);
+ subtype.add(SubType.SOLDIER);
+ color.setWhite(true);
+
+ this.addAbility(new SimpleStaticAbility(new SetBasePowerToughnessSourceEffect(
+ xValue
+ ).setText("this creature's power and toughness are each equal to the number of artifacts and/or creatures you control")));
+ }
+
+ protected GnomeSoldierStarStarToken(final GnomeSoldierStarStarToken token) {
+ super(token);
+ }
+
+ public GnomeSoldierStarStarToken copy() {
+ return new GnomeSoldierStarStarToken(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/watchers/common/ManaPaidObjectSourceWatcher.java b/Mage/src/main/java/mage/watchers/common/ManaPaidObjectSourceWatcher.java
new file mode 100644
index 00000000000..70e3717f976
--- /dev/null
+++ b/Mage/src/main/java/mage/watchers/common/ManaPaidObjectSourceWatcher.java
@@ -0,0 +1,54 @@
+package mage.watchers.common;
+
+import mage.MageObject;
+import mage.MageObjectReference;
+import mage.constants.WatcherScope;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ManaPaidEvent;
+import mage.watchers.Watcher;
+
+import java.util.*;
+
+/**
+ * @author Susucr
+ */
+public class ManaPaidObjectSourceWatcher extends Watcher {
+
+ // what is paid -> set of all MageObject sources used to pay for the mana.
+ private final Map> payMap = new HashMap<>();
+
+ public ManaPaidObjectSourceWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() != GameEvent.EventType.MANA_PAID) {
+ return;
+ }
+
+ ManaPaidEvent manaEvent = (ManaPaidEvent) event;
+ UUID paid = manaEvent.getSourcePaidId();
+ MageObject sourceObject = manaEvent.getSourceObject();
+ if (paid == null || sourceObject == null) {
+ return;
+ }
+
+ payMap
+ .computeIfAbsent(new MageObjectReference(paid, game), x -> new HashSet<>())
+ .add(new MageObjectReference(sourceObject, game));
+ }
+
+ public boolean checkManaFromSourceWasUsedToPay(MageObjectReference sourceOfMana, MageObjectReference paidObject) {
+ return payMap
+ .getOrDefault(paidObject, Collections.emptySet())
+ .contains(sourceOfMana);
+ }
+
+ @Override
+ public void reset() {
+ payMap.clear();
+ super.reset();
+ }
+}