Merge pull request #973 from kevlahnota/master
Support for AKH/HOU Mechanics
This commit is contained in:
@@ -41166,8 +41166,7 @@ type=Enchantment
|
||||
[card]
|
||||
name=Flagstones of Trokair
|
||||
auto={T}:Add{W}
|
||||
aicode=activate moveTo(myBattlefield) and!(tap(noevent))! target(plains|myLibrary)
|
||||
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
|
||||
auto=@movedTo(this|graveyard) from(battlefield):name(search card) ability$!moveTo(myBattlefield) and!(tap(noevent))! target(plains|myLibrary)!$ controller
|
||||
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
|
||||
[/card]
|
||||
@@ -64909,7 +64908,7 @@ toughness=5
|
||||
name=Krosan Verge
|
||||
auto=tap(noevent)
|
||||
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.
|
||||
type=Land
|
||||
[/card]
|
||||
@@ -79818,7 +79817,7 @@ name=Niblis of the Breath
|
||||
abilities=flying
|
||||
auto={U}{T}:may tap 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}
|
||||
type=Creature
|
||||
subtype=Spirit
|
||||
@@ -90652,8 +90651,8 @@ toughness=5
|
||||
[card]
|
||||
name=Quarantine Field
|
||||
auto=counter(0/0,xx,Isolation)
|
||||
auto=(blink)forsrc target(<prexx>*[-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)
|
||||
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.
|
||||
mana={X}{X}{W}{W}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
@@ -109371,7 +109370,7 @@ type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
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)
|
||||
abilities=playershroud
|
||||
auto=preventalldamage to(controller)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
public:
|
||||
@@ -5174,6 +5196,7 @@ public:
|
||||
list<int> oldcolors;
|
||||
list<int> oldtypes;
|
||||
vector<int> dontremove;
|
||||
bool removemc;
|
||||
bool addNewColors;
|
||||
bool remove;
|
||||
bool removeCreatureSubtypes;
|
||||
@@ -7290,6 +7313,57 @@ public:
|
||||
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
|
||||
class ATriggerRegen: public InstantAbility
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
bool blinked;
|
||||
bool isExtraCostTarget;
|
||||
bool morphed;
|
||||
bool exerted;
|
||||
bool turningOver;
|
||||
bool isMorphed;
|
||||
bool isFlipped;
|
||||
|
||||
@@ -205,6 +205,12 @@ struct WEventCardCycle : public WEventCardUpdate {
|
||||
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
|
||||
//before : attacker that card was blocking previously
|
||||
//after: attacker that card is blocking now
|
||||
|
||||
@@ -1040,7 +1040,7 @@ void ActionStack::Update(float dt)
|
||||
if (getCurrentTutorial() && (observer->players[0]->isHuman() || observer->players[1]->isHuman() ) )
|
||||
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())
|
||||
return;//dont do any of this if a menuobject exist.
|
||||
|
||||
|
||||
@@ -6046,6 +6046,7 @@ ATransformer::ATransformer(GameObserver* observer, int id, MTGCardInstance * sou
|
||||
}
|
||||
myCurrentTurn = 1000;
|
||||
//this subkeyword adds a color without removing the existing colors.
|
||||
removemc = (sabilities.find("removemc") != string::npos);
|
||||
addNewColors = (sabilities.find("newcolors") != string::npos);
|
||||
remove = (stypes.find("removealltypes") != string::npos);
|
||||
removeCreatureSubtypes = (stypes.find("removecreaturesubtypes") != string::npos);
|
||||
@@ -6235,6 +6236,9 @@ for (it = types.begin(); it != types.end(); it++)
|
||||
_target->addbaseT(val->getValue());
|
||||
delete val;
|
||||
}
|
||||
//remove manacost
|
||||
if(removemc)
|
||||
_target->getManaCost()->resetCosts();
|
||||
|
||||
return MTGAbility::addToGame();
|
||||
}
|
||||
|
||||
@@ -439,7 +439,7 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
|
||||
if (grave->hasType("land")) checkTypesAmount++;
|
||||
if (grave->hasType("artifact")) checkTypesAmount++;
|
||||
if (grave->hasType("planeswalker")) checkTypesAmount++;
|
||||
if (grave->hasType("tribal")) checkTypesAmount++;
|
||||
if (grave->hasType("tribal")) checkTypesAmount++;
|
||||
if (checkTypesAmount < 4)
|
||||
return 0;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe
|
||||
if (grave->hasType("land")) checkTypesAmount++;
|
||||
if (grave->hasType("artifact")) checkTypesAmount++;
|
||||
if (grave->hasType("planeswalker")) checkTypesAmount++;
|
||||
if (grave->hasType("tribal")) checkTypesAmount++;
|
||||
if (grave->hasType("tribal")) checkTypesAmount++;
|
||||
if (checkTypesAmount > 3)
|
||||
return 0;
|
||||
}
|
||||
@@ -1070,6 +1070,10 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell
|
||||
if (TargetChooser *tc = parseSimpleTC(s,"phasedin", card))
|
||||
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
|
||||
//Card card attacked and is blocked
|
||||
found = s.find("combat(");
|
||||
@@ -2928,7 +2932,20 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
((AManifest*)a)->withenchant = true;
|
||||
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
|
||||
found = s.find("provoke");
|
||||
if (found != string::npos)
|
||||
|
||||
@@ -224,6 +224,7 @@ void MTGCardInstance::initMTGCI()
|
||||
blinked = false;
|
||||
isExtraCostTarget = false;
|
||||
morphed = false;
|
||||
exerted = false;
|
||||
turningOver = false;
|
||||
isMorphed = false;
|
||||
MeldedFrom = "";
|
||||
|
||||
@@ -1219,12 +1219,12 @@ int MTGDeck::save(const string& destFileName, bool useExpandedDescriptions, cons
|
||||
void MTGDeck::printDetailedDeckText(std::ofstream& file )
|
||||
{
|
||||
ostringstream currentCard, creatures, lands, spells, types;
|
||||
ostringstream ss_creatures, ss_lands, ss_spells;
|
||||
int numberOfCreatures = 0;
|
||||
int numberOfSpells = 0;
|
||||
int numberOfLands = 0;
|
||||
ostringstream ss_creatures, ss_lands, ss_spells;
|
||||
int numberOfCreatures = 0;
|
||||
int numberOfSpells = 0;
|
||||
int numberOfLands = 0;
|
||||
|
||||
map<int, int>::iterator it;
|
||||
map<int, int>::iterator it;
|
||||
for (it = cards.begin(); it != cards.end(); it++)
|
||||
{
|
||||
int cardId = it->first;
|
||||
@@ -1271,29 +1271,29 @@ void MTGDeck::printDetailedDeckText(std::ofstream& file )
|
||||
|
||||
currentCard <<endl;
|
||||
setInfo = NULL;
|
||||
// Add counter to know number of creatures, non-creature spells and lands present in the deck
|
||||
// Add counter to know number of creatures, non-creature spells and lands present in the deck
|
||||
if ( card->data->isLand() )
|
||||
{
|
||||
{
|
||||
lands<< currentCard.str();
|
||||
numberOfLands+=nbCards;
|
||||
}
|
||||
numberOfLands+=nbCards;
|
||||
}
|
||||
else if ( card->data->isCreature() )
|
||||
{
|
||||
{
|
||||
creatures << currentCard.str();
|
||||
numberOfCreatures+=nbCards;
|
||||
}
|
||||
numberOfCreatures+=nbCards;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
spells << currentCard.str();
|
||||
numberOfSpells+=nbCards;
|
||||
}
|
||||
numberOfSpells+=nbCards;
|
||||
}
|
||||
currentCard.str("");
|
||||
}
|
||||
ss_creatures << numberOfCreatures;
|
||||
ss_spells << numberOfSpells;
|
||||
ss_lands << numberOfLands;
|
||||
ss_creatures << numberOfCreatures;
|
||||
ss_spells << numberOfSpells;
|
||||
ss_lands << numberOfLands;
|
||||
|
||||
file << getCardBlockText( "Creatures x " + ss_creatures.str(), creatures.str() ) << endl;
|
||||
file << getCardBlockText( "Creatures x " + ss_creatures.str(), creatures.str() ) << endl;
|
||||
file << getCardBlockText( "Spells x " + ss_spells.str(), spells.str() ) << endl;
|
||||
file << getCardBlockText( "Lands x " + ss_lands.str(), lands.str() ) << endl;
|
||||
creatures.str("");
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -1125,13 +1132,25 @@ void MTGInPlay::untapAll()
|
||||
card->setUntapping();
|
||||
if (!card->basicAbilities[(int)Constants::DOESNOTUNTAP] && !card->basicAbilities[(int)Constants::SHACKLER])
|
||||
{
|
||||
if (card->frozen < 1)
|
||||
if(card->exerted)
|
||||
{
|
||||
card->attemptUntap();
|
||||
card->exerted = false;
|
||||
if (card->frozen >= 1)
|
||||
{
|
||||
card->frozen = 0;
|
||||
}
|
||||
}
|
||||
if (card->frozen >= 1)
|
||||
else
|
||||
{
|
||||
card->frozen = 0;
|
||||
card->exerted = false;
|
||||
if (card->frozen < 1)
|
||||
{
|
||||
card->attemptUntap();
|
||||
}
|
||||
if (card->frozen >= 1)
|
||||
{
|
||||
card->frozen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,11 @@ WEventCardUpdate(card)
|
||||
{
|
||||
}
|
||||
|
||||
WEventCardExerted::WEventCardExerted(MTGCardInstance * card) :
|
||||
WEventCardUpdate(card)
|
||||
{
|
||||
}
|
||||
|
||||
WEventVampire::WEventVampire(MTGCardInstance * card,MTGCardInstance * source,MTGCardInstance * victem) :
|
||||
WEventCardUpdate(card),source(source),victem(victem)
|
||||
{
|
||||
@@ -377,6 +382,12 @@ Targetable * WEventCardCycle::getTarget(int target)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventCardExerted::getTarget(int target)
|
||||
{
|
||||
if (target) return card;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventCardAttackedNotBlocked::getTarget(int target)
|
||||
{
|
||||
if (target) return card;
|
||||
|
||||
Reference in New Issue
Block a user