Merge pull request #973 from kevlahnota/master

Support for AKH/HOU Mechanics
This commit is contained in:
Anthony Calosa
2017-08-03 10:36:15 +08:00
committed by GitHub
11 changed files with 166 additions and 34 deletions

View File

@@ -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)

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
{
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

View File

@@ -90,6 +90,7 @@ public:
bool blinked;
bool isExtraCostTarget;
bool morphed;
bool exerted;
bool turningOver;
bool isMorphed;
bool isFlipped;

View File

@@ -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

View File

@@ -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.

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -224,6 +224,7 @@ void MTGCardInstance::initMTGCI()
blinked = false;
isExtraCostTarget = false;
morphed = false;
exerted = false;
turningOver = false;
isMorphed = false;
MeldedFrom = "";

View File

@@ -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("");

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)
{
@@ -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;
}
}
}
}

View File

@@ -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;