Add support for Amonkhet Mechanics

and fix some cards.
Added exerted trigger, event and add removemc keyword inside transforms
ability so we can soft code Embalm and Eternalize...
This commit is contained in:
Anthony Calosa
2017-08-03 09:49:37 +08:00
parent 1f670b9919
commit 6bd09e42e0
11 changed files with 166 additions and 34 deletions
+6 -7
View File
@@ -41166,8 +41166,7 @@ type=Enchantment
[card] [card]
name=Flagstones of Trokair name=Flagstones of Trokair
auto={T}:Add{W} auto={T}:Add{W}
aicode=activate moveTo(myBattlefield) and!(tap(noevent))! target(plains|myLibrary) auto=@movedTo(this|graveyard) from(battlefield):name(search card) ability$!moveTo(myBattlefield) and!(tap(noevent))! target(plains|myLibrary)!$ controller
auto=@movedTo(this|graveyard) from(battlefield):name(search card) reveal:plibrarycount optionone name(choose card) target(plains|reveal) moveto(ownerlibrary) and!( becomes(tobecast) ueot )! optiononeend optiontwo name(put back) target(<1>*|reveal) moveto(ownerlibrary) and!( all(*|reveal) moveto(ownerlibrary) and!(shuffle)! )! optiontwoend afterrevealed all(tobecast|mylibrary) moveto(ownerlibrary) and!(moveTo(myBattlefield) and!(tap(noevent))!)! afterrevealedend revealend
text={T}: Add {W} to your mana pool. -- When Flagstones of Trokair is put into a graveyard from the battlefield, you may search your library for a Plains card and put it onto the battlefield tapped. If you do, shuffle your library. text={T}: Add {W} to your mana pool. -- When Flagstones of Trokair is put into a graveyard from the battlefield, you may search your library for a Plains card and put it onto the battlefield tapped. If you do, shuffle your library.
type=Legendary Land type=Legendary Land
[/card] [/card]
@@ -64909,7 +64908,7 @@ toughness=5
name=Krosan Verge name=Krosan Verge
auto=tap(noevent) auto=tap(noevent)
auto={T}:Add{1} auto={T}:Add{1}
auto={2}{T}{S}:name(sacrifice to search) ability$! name(search forest) notatarget(forest|mylibrary) moveto(ownerbattlefield) and!(tap(noevent))! !$ controller && ability$! name(search plains) notatarget(plains|mylibrary) moveto(ownerbattlefield) and!(tap(noevent))! !$ controller auto={2}{T}{S}:name(sacrifice to search) transforms((,newability[ability$! name(search forest) notatarget(forest|mylibrary) moveto(ownerbattlefield) and!(tap(noevent))! !$ controller],newability[ability$! name(search plains) notatarget(plains|mylibrary) moveto(ownerbattlefield) and!(tap(noevent))! !$ controller])) oneshot
text=Krosan Verge enters the battlefield tapped. -- {T}: Add {1} to your mana pool. -- {2}, {T}, Sacrifice Krosan Verge: Search your library for a Forest card and a Plains card and put them onto the battlefield tapped. Then shuffle your library. text=Krosan Verge enters the battlefield tapped. -- {T}: Add {1} to your mana pool. -- {2}, {T}, Sacrifice Krosan Verge: Search your library for a Forest card and a Plains card and put them onto the battlefield tapped. Then shuffle your library.
type=Land type=Land
[/card] [/card]
@@ -79818,7 +79817,7 @@ name=Niblis of the Breath
abilities=flying abilities=flying
auto={U}{T}:may tap target(creature) auto={U}{T}:may tap target(creature)
auto={U}{T}:may untap target(creature) auto={U}{T}:may untap target(creature)
text=Flying -- Whenever Niblis of the Urn attacks, you may tap target creature. text=Flying -- {U}, {T}: You may tap or untap target creature.
mana={2}{U} mana={2}{U}
type=Creature type=Creature
subtype=Spirit subtype=Spirit
@@ -90652,8 +90651,8 @@ toughness=5
[card] [card]
name=Quarantine Field name=Quarantine Field
auto=counter(0/0,xx,Isolation) auto=counter(0/0,xx,Isolation)
auto=(blink)forsrc target(<prexx>*[-land]|opponentbattlefield) auto=this(variable{xx} >0) (blink)forsrc target(<upto:counter{0%0.1.Isolation}>*[-land]|opponentbattlefield)
text=Quarantine Field enters the battlefield with X isolation counters on it. -- When Quarantine Field enters the battlefield, for each isolation counter on it, exile up to one target nonland permanent an opponent controls until Quarantine Field leaves the battlefield. (WORKAROUND ONLY EXILES UP TO X AND NOT FOR EACH COUNTER) text=Quarantine Field enters the battlefield with X isolation counters on it. -- When Quarantine Field enters the battlefield, for each isolation counter on it, exile up to one target nonland permanent an opponent controls until Quarantine Field leaves the battlefield.
mana={X}{X}{W}{W} mana={X}{X}{W}{W}
type=Enchantment type=Enchantment
[/card] [/card]
@@ -109371,7 +109370,7 @@ type=Instant
[/card] [/card]
[card] [card]
name=Solitary Confinement name=Solitary Confinement
auto=upcost[{D(*|myhand)}] sacrifice auto=@each my upkeep :name(discard or sacrifice) ability$!if type(*|myhand)~morethan~0 then choice reject notatarget(*|myhand) _ choice sacrifice all(mystored)!$ controller
auto=phasealter(remove,draw,controller) auto=phasealter(remove,draw,controller)
abilities=playershroud abilities=playershroud
auto=preventalldamage to(controller) auto=preventalldamage to(controller)
+74
View File
@@ -1406,6 +1406,28 @@ public:
} }
}; };
class TrCardExerted: public Trigger
{
public:
TrCardExerted(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false) :
Trigger(observer, id, source, once, tc)
{
}
int triggerOnEventImpl(WEvent * event)
{
WEventCardExerted * e = dynamic_cast<WEventCardExerted *> (event);
if (!e) return 0;
if (!tc->canTarget(e->card)) return 0;
return 1;
}
TrCardExerted * clone() const
{
return NEW TrCardExerted(*this);
}
};
class TrCombatTrigger: public Trigger class TrCombatTrigger: public Trigger
{ {
public: public:
@@ -5174,6 +5196,7 @@ public:
list<int> oldcolors; list<int> oldcolors;
list<int> oldtypes; list<int> oldtypes;
vector<int> dontremove; vector<int> dontremove;
bool removemc;
bool addNewColors; bool addNewColors;
bool remove; bool remove;
bool removeCreatureSubtypes; bool removeCreatureSubtypes;
@@ -7290,6 +7313,57 @@ public:
return NEW AProvoke(*this); return NEW AProvoke(*this);
} }
}; };
//exert
class AExert: public InstantAbility
{
public:
MTGAbility * andAbility;
AExert(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
InstantAbility(observer, _id, _source)
{
target = _target;
andAbility = NULL;
}
int resolve()
{
MTGCardInstance * card = (MTGCardInstance *) target;
if (card)
{
card->exerted = true;
WEvent * e = NEW WEventCardExerted(card);
game->receiveEvent(e);
if(andAbility)
{
MTGAbility * andAbilityClone = andAbility->clone();
andAbilityClone->target = card;
if(andAbility->oneShot)
{
andAbilityClone->resolve();
SAFE_DELETE(andAbilityClone);
}
else
{
andAbilityClone->addToGame();
}
}
}
return 1;
}
const string getMenuText()
{
return "Exert";
}
virtual ostream& toString(ostream& out) const
{
out << "AAExert ::: (";
return InstantAbility::toString(out) << ")";
}
AExert * clone() const
{
return NEW AExert(*this);
}
};
//------------------ //------------------
//trigger regen //trigger regen
class ATriggerRegen: public InstantAbility class ATriggerRegen: public InstantAbility
+1
View File
@@ -90,6 +90,7 @@ public:
bool blinked; bool blinked;
bool isExtraCostTarget; bool isExtraCostTarget;
bool morphed; bool morphed;
bool exerted;
bool turningOver; bool turningOver;
bool isMorphed; bool isMorphed;
bool isFlipped; bool isFlipped;
+6
View File
@@ -205,6 +205,12 @@ struct WEventCardCycle : public WEventCardUpdate {
virtual Targetable * getTarget(int target); virtual Targetable * getTarget(int target);
}; };
//event when card is exerted.
struct WEventCardExerted : public WEventCardUpdate {
WEventCardExerted(MTGCardInstance * card);
virtual Targetable * getTarget(int target);
};
//Event when a card's "defenser" status changes //Event when a card's "defenser" status changes
//before : attacker that card was blocking previously //before : attacker that card was blocking previously
//after: attacker that card is blocking now //after: attacker that card is blocking now
+1 -1
View File
@@ -1040,7 +1040,7 @@ void ActionStack::Update(float dt)
if (getCurrentTutorial() && (observer->players[0]->isHuman() || observer->players[1]->isHuman() ) ) if (getCurrentTutorial() && (observer->players[0]->isHuman() || observer->players[1]->isHuman() ) )
return; return;
if (observer->mLayers->actionLayer()->menuObject || observer->LPWeffect) if (observer->mLayers->actionLayer()->menuObject)// || observer->LPWeffect) //test fix for hang for both legendary with action/reveal
if(observer->players[0]->isHuman() || observer->players[1]->isHuman()) if(observer->players[0]->isHuman() || observer->players[1]->isHuman())
return;//dont do any of this if a menuobject exist. return;//dont do any of this if a menuobject exist.
+4
View File
@@ -6046,6 +6046,7 @@ ATransformer::ATransformer(GameObserver* observer, int id, MTGCardInstance * sou
} }
myCurrentTurn = 1000; myCurrentTurn = 1000;
//this subkeyword adds a color without removing the existing colors. //this subkeyword adds a color without removing the existing colors.
removemc = (sabilities.find("removemc") != string::npos);
addNewColors = (sabilities.find("newcolors") != string::npos); addNewColors = (sabilities.find("newcolors") != string::npos);
remove = (stypes.find("removealltypes") != string::npos); remove = (stypes.find("removealltypes") != string::npos);
removeCreatureSubtypes = (stypes.find("removecreaturesubtypes") != string::npos); removeCreatureSubtypes = (stypes.find("removecreaturesubtypes") != string::npos);
@@ -6235,6 +6236,9 @@ for (it = types.begin(); it != types.end(); it++)
_target->addbaseT(val->getValue()); _target->addbaseT(val->getValue());
delete val; delete val;
} }
//remove manacost
if(removemc)
_target->getManaCost()->resetCosts();
return MTGAbility::addToGame(); return MTGAbility::addToGame();
} }
+18 -1
View File
@@ -1070,6 +1070,10 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell
if (TargetChooser *tc = parseSimpleTC(s,"phasedin", card)) if (TargetChooser *tc = parseSimpleTC(s,"phasedin", card))
return NEW TrCardPhasesIn(observer, id, card, tc,once); return NEW TrCardPhasesIn(observer, id, card, tc,once);
//Card Exerted
if (TargetChooser *tc = parseSimpleTC(s,"exerted", card))
return NEW TrCardExerted(observer, id, card, tc,once);
//CombatTrigger //CombatTrigger
//Card card attacked and is blocked //Card card attacked and is blocked
found = s.find("combat("); found = s.find("combat(");
@@ -2928,7 +2932,20 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
((AManifest*)a)->withenchant = true; ((AManifest*)a)->withenchant = true;
return a; return a;
} }
//exert
found = s.find("exert");
if (found != string::npos)
{
MTGAbility * a = NEW AExert(observer, id, card, target);
a->oneShot = 1;
if(storedAndAbility.size())
{
string stored = storedAndAbility;
storedAndAbility.clear();
((AExert*)a)->andAbility = parseMagicLine(stored, id, spell, card);
}
return a;
}
//provoke //provoke
found = s.find("provoke"); found = s.find("provoke");
if (found != string::npos) if (found != string::npos)
+1
View File
@@ -224,6 +224,7 @@ void MTGCardInstance::initMTGCI()
blinked = false; blinked = false;
isExtraCostTarget = false; isExtraCostTarget = false;
morphed = false; morphed = false;
exerted = false;
turningOver = false; turningOver = false;
isMorphed = false; isMorphed = false;
MeldedFrom = ""; MeldedFrom = "";
+19
View File
@@ -554,6 +554,13 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
} }
} }
} }
//remove exerted if changing controls
if((to == g->players[0]->game->battlefield && from == g->players[1]->game->battlefield)||
(to == g->players[1]->game->battlefield && from == g->players[0]->game->battlefield))
{
if(ret->exerted)
ret->exerted = false;
}
} }
if(!asCopy) if(!asCopy)
{ {
@@ -1125,6 +1132,17 @@ void MTGInPlay::untapAll()
card->setUntapping(); card->setUntapping();
if (!card->basicAbilities[(int)Constants::DOESNOTUNTAP] && !card->basicAbilities[(int)Constants::SHACKLER]) if (!card->basicAbilities[(int)Constants::DOESNOTUNTAP] && !card->basicAbilities[(int)Constants::SHACKLER])
{ {
if(card->exerted)
{
card->exerted = false;
if (card->frozen >= 1)
{
card->frozen = 0;
}
}
else
{
card->exerted = false;
if (card->frozen < 1) if (card->frozen < 1)
{ {
card->attemptUntap(); card->attemptUntap();
@@ -1135,6 +1153,7 @@ void MTGInPlay::untapAll()
} }
} }
} }
}
} }
+11
View File
@@ -121,6 +121,11 @@ WEventCardUpdate(card)
{ {
} }
WEventCardExerted::WEventCardExerted(MTGCardInstance * card) :
WEventCardUpdate(card)
{
}
WEventVampire::WEventVampire(MTGCardInstance * card,MTGCardInstance * source,MTGCardInstance * victem) : WEventVampire::WEventVampire(MTGCardInstance * card,MTGCardInstance * source,MTGCardInstance * victem) :
WEventCardUpdate(card),source(source),victem(victem) WEventCardUpdate(card),source(source),victem(victem)
{ {
@@ -377,6 +382,12 @@ Targetable * WEventCardCycle::getTarget(int target)
return NULL; return NULL;
} }
Targetable * WEventCardExerted::getTarget(int target)
{
if (target) return card;
return NULL;
}
Targetable * WEventCardAttackedNotBlocked::getTarget(int target) Targetable * WEventCardAttackedNotBlocked::getTarget(int target)
{ {
if (target) return card; if (target) return card;